#include "tetriswindow.h"
#include <QColor>
#include <QPainter>
#include <QDebug>
#include <QKeyEvent>
#include <time.h>
#include <iostream>
#include <QMessageBox>
#include <QMenuBar>
#include "globalutils.h"
using namespace  std;
TetrisWindow::TetrisWindow(QWidget *parent) : QMainWindow(parent)
{
    //初始化
    init();
}

TetrisWindow::~TetrisWindow(){
    //回收内存
    if(pen != nullptr){
        delete pen;
    }
    if(brush != nullptr){
        delete brush;
    }
}

/**
 * 初始化
 * @brief TetrisWindow::init
 */
void TetrisWindow::init(){
    setWindowTitle(tr("俄罗斯方块"));
    setGeometry(400, 300, WIN_WIDTH, WIN_HEGIHT);
    setFixedSize(QSize(WIN_WIDTH, WIN_HEGIHT));
    //设置背景色
    QPalette palette = this->palette();
    palette.setColor(QPalette::ColorRole::Background, QColor(0x26, 0x32,0x38));
    this->setPalette(palette);
    //初始化菜单
    initMenu();
    //初始化看板
    initScoreBoard();
    //创建画笔和画刷
    pen = new QPen();
    brush = new QBrush();
}

void TetrisWindow::initMenu(){
    menu = new QMenu(this);
    menu->setTitle(tr("游戏"));

    helpMenu = new QMenu();
    helpMenu->setTitle(tr("帮助"));


    startGameAction = new QAction(this);
    startGameAction->setText("开始游戏");
    menu->addAction(startGameAction);

    pauseOrContinueGameAction = new QAction(this);
    pauseOrContinueGameAction->setText("暂停游戏");
    menu->addAction(pauseOrContinueGameAction);

    stopGameAction = new QAction(this);
    stopGameAction->setText("结束游戏");
    menu->addAction(stopGameAction);

    helpAction = new QAction(this);
    helpAction->setText("操作指南");
    helpMenu->addAction(helpAction);

    //添加到菜单栏
    menuBar()->addMenu(menu);
    menuBar()->addMenu(helpMenu);
    //事件绑定
    connect(startGameAction, SIGNAL(triggered()), this, SLOT(slotStartGame()));
    connect(pauseOrContinueGameAction, SIGNAL(triggered()), this, SLOT(slotPauseGame()));
    connect(stopGameAction, SIGNAL(triggered()), this, SLOT(slotStopGame()));
    connect(helpAction, SIGNAL(triggered()), this, SLOT(slotHelp()));
}


/**
 * 初始化看板
 * @brief TetrisWindow::initScoreBoard
 */
void TetrisWindow::initScoreBoard(){
    font.setPixelSize(20);
    pe.setColor(QPalette::WindowText,Qt::green);

    nextBlockLabel = new QLabel(this);
    nextBlockLabel->setText(tr("下一个:"));
    nextBlockLabel->setFont(font);
    nextBlockLabel->setPalette(pe);
    nextBlockLabel->setGeometry(GAME_WIDTH+10, 20, 80, 30);

    scoreLabel = new QLabel(this);
    scoreLabel->setText(tr("得分:"));
    scoreLabel->setFont(font);
    scoreLabel->setPalette(pe);
    scoreLabel->setGeometry(GAME_WIDTH+10, 200, 80, 30);

    scoreValueLabel = new QLabel(this);
    scoreValueLabel->setNum(0);
    font.setPixelSize(30);
    scoreValueLabel->setFont(font);
    scoreValueLabel->setPalette(pe);
    scoreValueLabel->setGeometry(GAME_WIDTH+80, 240, 80, 30);


}
/**
 * 开始游戏
 * @brief TetrisWindow::startGame
 */
void TetrisWindow::startGame(){
    gameStatus = GameStatus::RUNNING;
    score = 0;
    //创建方块
    if(currentBlock == nullptr){
        currentBlock = new Block(Block::I, Block::LEFT, this);
        nextBlock = new Block(Block::I, Block::LEFT, this);
        timer = new QTimer(this);
        QObject::connect(timer, SIGNAL(timeout()), this, SLOT(slotAutoDown()));
    }
    initNextBlock(); //初始化下一个方块
    reSetBlock(); //设置到当前移动的方块
//    for(int i = 0; i<4; i++){
//        for(int j=0; j <4; j++){
//            cout << currentBlock->block[i][j]<<",";
//        }
//        cout << "\n";
//    }
    update();
    timer->start(500);//开启自动下移
}

/**
 * 暂停(继续)游戏
 * @brief TetrisWindow::pauseGame
 */
void TetrisWindow::pauseOrContinueGame(){
    if(gameStatus == GameStatus::RUNNING){
        gameStatus = GameStatus::PAUSE;
        timer->stop();
        pauseOrContinueGameAction->setText("继续游戏");
    }else{
        gameStatus = GameStatus::RUNNING;
        timer->start(500);
        pauseOrContinueGameAction->setText("暂停游戏");
    }
}

/**
 * 游戏结束
 * @brief TetrisWindow::gameOver
 */
void TetrisWindow::gameOver(){
    timer->stop();
    gameStatus = GameStatus::STOP;
    QMessageBox::about(this, "失败","GameOver");
    reSetBlocks();
    update();
}

/**
 * 重置
 * @brief TetrisWindow::reSetBlock
 */
void TetrisWindow::reSetBlocks(){
    for(int i = 0; i < GAME_HEGIHT/GAME_GRID_SIZE; i++){
        for(int j = 0; j < GAME_WIDTH/GAME_GRID_SIZE; j++){
            blocks[i][j] = 0;
        }
    }
}

/**
 * 将currentBlock方块复制到地图
 * @brief TetrisWindow::copyBlock
 */
void TetrisWindow::copyBlock(){
    int blocks_i =0;
    int blocks_j =0;
    for(int i = 0;  i < 4; i++){ //行  y坐标
        for(int j = 0; j < 4; j++){ // 列 x坐标
            blocks_i = getCurrentBlocksI(i);
            blocks_j = getCurrentBlocksJ(j);
            //越界判断
            if(blocks_i < 0 || blocks_j < 0 || blocks_i >= GAME_HEGIHT/GAME_GRID_SIZE || blocks_j >= GAME_WIDTH/GAME_GRID_SIZE){
                continue;
            }
            if(currentBlock->block[i][j] == 1){
                blocks[blocks_i][blocks_j] = currentBlock->block[i][j];
            }
         }

    }
}

/**
 * 左移
 * @brief TetrisWindow::leftMove
 */
void TetrisWindow::leftMove(){
    for(int i = 3; i>=0;i--){ //从第三行倒过来数
        for(int j = 0; j < 4; j++){
            if(currentBlock->block[i][j] ==1){
                //到达做边界或发生碰撞
                if(getCurrentBlocksJ(j)<=0  || blocks[getCurrentBlocksI(i)][getCurrentBlocksJ(j)-1] ==1)
                    return;
            }
        }
    }
    currentBlock->x--;
    update();
}

/**
 * 右移
 * @brief TetrisWindow::rightMove
 */
void TetrisWindow::rightMove(){
    for(int i = 3; i>=0;i--){ //从第三行倒过来数
        for(int j = 0; j < 4; j++){
            if(currentBlock->block[i][j] ==1){
                //到达做边界或发生碰撞
                if(getCurrentBlocksJ(j) >= GAME_WIDTH/GAME_GRID_SIZE-1  || blocks[getCurrentBlocksI(i)][getCurrentBlocksJ(j)+1] ==1)
                    return;
            }
        }
    }
    currentBlock->x++;
    update();
}
/**
 * 下移
 * @brief TetrisWindow::downMove
 */
void TetrisWindow::downMove(){
    if(gameStatus == GameStatus::STOP || gameStatus == GameStatus::PAUSE){
        return;
    }
    for(int i = 3; i>=0;i--){ //从第三行倒过来数
        for(int j = 0; j < 4; j++){
            if(currentBlock->block[i][j] ==1){
                     // 到达底部 || 或碰撞了
                    if(getCurrentBlocksI(i)>=GAME_HEGIHT/GAME_GRID_SIZE-1  || blocks[getCurrentBlocksI(i+1)][getCurrentBlocksJ(j)] ==1){
                        if(currentBlock->y < 0){
                            gameOver();
                            return;
                        }
                        copyBlock();
                        checkGetScore();
                        reSetBlock();
                        return;
                    }
            }
        }
    }
    currentBlock->y++;
    update();
}

/**
 * 检查是否得分
 * @brief TetrisWindow::checkGetScore
 */
void TetrisWindow::checkGetScore(){
    for(int i = currentBlock->y; i < GAME_HEGIHT/GAME_GRID_SIZE; i++){
        int j;
        for(j = 0; j < GAME_WIDTH/GAME_GRID_SIZE; j++){
            if(blocks[i][j] == 0){
                break;
            }
        }
        if(j == GAME_WIDTH/GAME_GRID_SIZE){ //得分
           score += (score * 0.5 + 10); //增加分数
           scoreValueLabel->setNum(score);
           clearI(i);
        }
    }

}

/**
 * 删除得分行
 * @brief TetrisWindow::clearI
 * @param i
 */
void TetrisWindow::clearI(int i){
    //当前行满了，消除
    for(int j = 0; j < GAME_WIDTH/GAME_GRID_SIZE; j++){
        blocks[i][j] = 0;
    }
    //上面的行下移一行
    for(int x = i; x > 0; x--){
        int k=0;
        for(int j = 0; j < GAME_WIDTH/GAME_GRID_SIZE; j++){
            blocks[x][j]  = blocks[x-1][j];
            if(blocks[x][j] == 0){
                k++;
            }
        }
        if(k == GAME_WIDTH/GAME_GRID_SIZE){ //上面的行都是0不用循环了
            break;
        }

    }
    update();

}

/**
 * 变形
 * @brief TetrisWindow::changeVariant
 */
void TetrisWindow::changeVariant(){
    //判断空间是否允许变形
    if(currentBlock->x < 0 || currentBlock->x+3 > GAME_WIDTH/GAME_GRID_SIZE -1){ //x边界  判断
        return;
    }
    if(currentBlock->y + 3 > GAME_HEGIHT/GAME_GRID_SIZE-1){ //y边界判断
        return;
    }
    //方块边界判断
    for(int i = 0; i < 4; i++){
        for(int j = 0; j < 4; j++){
            if(blocks[getCurrentBlocksI(i)][getCurrentBlocksJ(j)] == 1){
                return;
            }
        }
    }

    currentBlock->change();
    update();
}

/**
 * 重置方块的形状,恢复位置（相当于产生一个新的方块）
 * @brief TetrisWindow::reSetBlock
 */
void TetrisWindow::reSetBlock(){
    //把下一个方块的类型复制给当前方块
    currentBlock->copy(*nextBlock);
    currentBlock->x = GAME_WIDTH/GAME_GRID_SIZE/2 - 2;//位置 在中间
    currentBlock->y = -4; //刚好在边界外面
    initNextBlock();//初始化下一个方块
}

/**
 * 初始化下一个方块
 * @brief TetrisWindow::initNextBlock
 */
void TetrisWindow::initNextBlock(){
    nextBlock->setType(getRandomType(), getRandomSubType());
}

/**
 * 随机获取一种方块类型
 * @brief TetrisWindow::getRandomType
 * @return
 */
Block::BlockType TetrisWindow::getRandomType(){
    uint seed_x = static_cast<uint>(clock());
    int i = GlobalUtils::getRandomNum(seed_x + 12,7); //获取随机数
    switch (i) { //I, J, L, O, S, T, Z
        case 0:
            return Block::BlockType::I;
        case 1:
            return Block::BlockType::J;
        case 2:
            return Block::BlockType::L;
        case 3:
            return Block::BlockType::O;
        case 4:
            return Block::BlockType::S;
        case 5:
            return Block::BlockType::T;
        case 6:
            return Block::BlockType::Z;
    }
    return Block::I;


}
/**
 * 随机获取一种变形
 * @brief TetrisWindow::getRandomSubType
 * @return
 */
Block::Variant TetrisWindow::getRandomSubType(){
    uint seed_x = static_cast<uint>(clock());
    int i = GlobalUtils::getRandomNum(seed_x + 13,4); //获取随机数
    switch (i) {
        case 0:
            return Block::Variant::LEFT;
        case 1:
            return Block::Variant::UP;
        case 2:
            return Block::Variant::RIGHT;
        case 3:
            return Block::Variant::DOWN;
    }
    return Block::Variant::LEFT;
}

/**
 * 计算当前方块(4*4)中第churrentI行是地图中的第几行
 * @brief TetrisWindow::getCurrentBlocksI
 * @param churrentI 第几行(0-3)
 * @return
 */
int TetrisWindow::getCurrentBlocksI(int currentI){
    return currentI+currentBlock->y;

}
/**
 * 计算当前方块(4*4)中第churrentJ列是地图中的第几列
 * @brief TetrisWindow::getCurrentBlocksJ
 * @param currentJ
 * @return
 */
int TetrisWindow::getCurrentBlocksJ(int currentJ){
    return currentJ+currentBlock->x;

}

/**
 * 复写绘制函数
 * @brief TetrisWindow::paintEvent
 */
void TetrisWindow::paintEvent(QPaintEvent *){
    QPainter painter(this);
    drawGb(painter);
    if(gameStatus == GameStatus::STOP){
        return;
    }
    drawBlocks(painter);
    drawCurrentBlock(painter);
    drawNextBlock(painter);
}

/**
 * 键盘事件
 * @brief TetrisWindow::keyPressEvent
 * @param event
 */
void TetrisWindow::keyPressEvent(QKeyEvent *event){
    if(gameStatus == GameStatus::STOP || gameStatus == GameStatus::PAUSE){return;}
    switch (event->key()) {
        case Qt::Key::Key_A:
            leftMove(); //左移
            break;
        case Qt::Key::Key_D:
            rightMove(); //右移
            break;
        case Qt::Key::Key_S:
            downMove(); //下移
            break;
        case Qt::Key::Key_Space:
            changeVariant();//变形
            break;
    }
}

/**
 * 绘制背景
 * @brief TetrisWindow::drawGb
 * @param painter
 */
void TetrisWindow::drawGb(QPainter &painter){
    pen->setColor(QColor(0x50, 0x50,0x50));
    painter.setPen(*pen);
    //纵向 线
    int i;
    for( i = 1; i <= GAME_WIDTH  / GAME_GRID_SIZE;i ++){
        painter.drawLine(i * GAME_GRID_SIZE, 0, i * GAME_GRID_SIZE, GAME_HEGIHT);
    }
    //横向
    for(int i = 1; i <= GAME_HEGIHT / GAME_GRID_SIZE; i++){
        painter.drawLine(0, i * GAME_GRID_SIZE, GAME_WIDTH, i * GAME_GRID_SIZE);
    }
}

/**
 * 绘制方块
 * @brief TetrisWindow::drawBlocks
 * @param painter
 */
void TetrisWindow::drawBlocks(QPainter &painter){
    pen->setColor(Qt::green);
    brush->setStyle(Qt::BrushStyle::SolidPattern);
    brush->setColor(Qt::yellow);
    painter.setPen(*pen);
    painter.setBrush(*brush);

    for(int i = 0; i < GAME_HEGIHT/GAME_GRID_SIZE; i++){   //行    i->y 坐标
        for(int j = 0; j < GAME_WIDTH/GAME_GRID_SIZE; j++){ //列   j->x 坐标
            if(blocks[i][j] == 1){
                //矩形
                painter.drawRect(j * GAME_GRID_SIZE, i * GAME_GRID_SIZE, GAME_GRID_SIZE, GAME_GRID_SIZE);
            }
        }
    }
}
/**
 * 绘制当前在活动的方块
 * @brief TetrisWindow::drawCurrentBlock
 * @param painter
 */
void TetrisWindow::drawCurrentBlock(QPainter &painter){
    int blocks_i =0; //活动方块在地图中的坐标
    int blocks_j =0;
    for(int i = 0;  i < 4; i++){ //行  y坐标
        for(int j = 0; j < 4; j++){ // 列 x坐标
            blocks_i = getCurrentBlocksI(i);
            blocks_j = getCurrentBlocksJ(j);
            //越界判断
            if(blocks_i < 0 || blocks_j < 0 || blocks_i >= GAME_HEGIHT/GAME_GRID_SIZE || blocks_j >= GAME_WIDTH/GAME_GRID_SIZE){
                continue;
            }
            if(currentBlock->block[i][j] == 1){
                //矩形
                painter.drawRect(blocks_j * GAME_GRID_SIZE, blocks_i * GAME_GRID_SIZE, GAME_GRID_SIZE, GAME_GRID_SIZE);
            }
        }
    }
}

/**
 * 绘制下一个方块
 * @brief TetrisWindow::drawNextBlock
 * @param painter
 */
void TetrisWindow::drawNextBlock(QPainter &painter){
    for(int i = 0; i < 4; i++){
        for(int j = 0; j < 4; j++){
            if(nextBlock->block[i][j] == 1){
                //矩形
                painter.drawRect(GAME_WIDTH + 50 + j * GAME_GRID_SIZE, 80 + i * GAME_GRID_SIZE, GAME_GRID_SIZE, GAME_GRID_SIZE);
            }
        }
    }

}

/**
 * 自动下移动
 * @brief TetrisWindow::slotAutoDown
 */
void TetrisWindow::slotAutoDown(){
    downMove();
}

/**
 * 暂停游戏
 * @brief TetrisWindow::slotPauseGame
 */
void TetrisWindow::slotPauseGame(){
    pauseOrContinueGame();
}
/**
 * 开始游戏
 * @brief TetrisWindow::slotStartGame
 */
void TetrisWindow::slotStartGame(){
    startGame();
}
/**
 * 停止游戏
 * @brief TetrisWindow::slotStopGame
 */
void TetrisWindow::slotStopGame(){
    gameOver();
}

/**
 * 帮助信息
 * @brief TetrisWindow::slotHelp
 */
void TetrisWindow::slotHelp(){
       QMessageBox::about(this,tr("操作提示"),tr("左移：A键\n右移：D键\n下移：S键\n变形：空格键"));
}
